#include "base/core/os/debug.h"
#include "base/core/os/os_head.h"
#include <stdio.h>
#include "base/core/os/string.h"
#include "base/core/com_define.h"
#include "base/core/char_operation.h"

static unsigned g_codePage = CP_ACP;

enum ConSolasFontColor 
{
    CONSOLAS_FONT_COLOR_DARKBLUE = 1,
    CONSOLAS_FONT_COLOR_DARKGREEN,
    CONSOLAS_FONT_COLOR_DARKTEAL,
    CONSOLAS_FONT_COLOR_DARKRED,
    CONSOLAS_FONT_COLOR_DARKPINK,
    CONSOLAS_FONT_COLOR_DARKYELLOW,
    CONSOLAS_FONT_COLOR_GRAY,
    CONSOLAS_FONT_COLOR_DARKGRAY,
    CONSOLAS_FONT_COLOR_BLUE,
    CONSOLAS_FONT_COLOR_GREEN,
    CONSOLAS_FONT_COLOR_TEAL,
    CONSOLAS_FONT_COLOR_RED,
    CONSOLAS_FONT_COLOR_PINK,
    CONSOLAS_FONT_COLOR_YELLOW,
    CONSOLAS_FONT_COLOR_WHITE
};

int ErrorNO() 
{
	return static_cast<int>(GetLastError());
}

void SetErrorNO(int err_no) 
{
	SetLastError(err_no);
}

char* ErrorMsg(int err_no, char *buf, size_t len) 
{
	MMO_ASSERT(buf);
	LPVOID msg_buf;

	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
				FORMAT_MESSAGE_FROM_SYSTEM |
				FORMAT_MESSAGE_IGNORE_INSERTS,
				NULL,
				(DWORD)err_no,
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
				(LPTSTR)&msg_buf,
				0, NULL);

	MMO_ASSERT(len > 0);
	SafeCopyString(buf, len, reinterpret_cast<const char*>(msg_buf));
	LocalFree(msg_buf);
	return buf;
}

void  SetDebugOutputCodePage(unsigned codePage) 
{
	g_codePage = codePage;
}

void  OutputToConsole(const char * info) 
{
    if (info == NULL || info[0] == '\0')
        return;

    static const short BACKGROUND_BLACK = 0;
    short BackgroundColor = BACKGROUND_BLACK;
    ConSolasFontColor color = CONSOLAS_FONT_COLOR_DARKGREEN;
    HANDLE outPutHandle = GetStdHandle(STD_OUTPUT_HANDLE);;

    if (strstr(info, "ERROR")) 
	{
        color = CONSOLAS_FONT_COLOR_WHITE;
        BackgroundColor = BACKGROUND_RED;
        putc('\a', stdout);
    }
    else if (strstr(info, " fail")) 
	{
        color = CONSOLAS_FONT_COLOR_WHITE;
        BackgroundColor = BACKGROUND_RED | BACKGROUND_GREEN;
        putc('\a', stdout);
    }

    // try convert to unicode for show content
    wchar_t infoW[LOG_BUFFER_LENGTH];
    int length = MultiByteToWideChar(g_codePage, 0, info, -1, infoW, countof(infoW) - 3);
    SetConsoleTextAttribute(outPutHandle, (WORD)(color | BackgroundColor));
    if (length > 0) 
	{
        // for cbMultiByte == -1, return length include terminal \0'
        --length;
        infoW[length++] = '\r';
        infoW[length++] = '\n';
        infoW[length  ] = '\0';
        DWORD writeNummber = 0;
        WriteConsoleW(outPutHandle, infoW, length, &writeNummber, nullptr);
        OutputDebugStringW(infoW);
    }
    else 
	{
        printf("%s\r\n", info);
        OutputDebugStringA(info);
        OutputDebugStringA("\r\n");
    }
    SetConsoleTextAttribute(outPutHandle, (WORD)(CONSOLAS_FONT_COLOR_DARKGREEN | BACKGROUND_BLACK));
}

bool  OutputFmtToConsole(const char * format, ...) 
{
    bool result  = false;    
    va_list args;
    char  info[LOG_BUFFER_LENGTH];
    int lengh = 0;

    MMOLOG_ASSERT_EXIT(format);

    va_start(args, format);
    lengh = vsnprintf(info, sizeof(info), format, args);
    va_end(args);

    if (lengh < 0 || lengh >= countof(info)) 
	{
        lengh = countof(info) - 1;
        info[lengh] = '\0';
    }

    if (lengh > 0) OutputToConsole(info);
	result = true;
Exit0:
  return result;
}

void  WriteDump(const char * file_path, const char * sig_info)
{
	_UNUSE(sig_info);
	_UNUSE(file_path);
}
